package com.wangxin.study8.threadtest;


import java.util.concurrent.CountDownLatch;

/**
 * @author jojo.wang
 * @title: CountDownLatchTest
 * @projectName study8
 * @description: CountDownLatch是一个同步工具类，它允许一个或多个线程一直等待，直到其他线程的操作执行完后再执行。
 * 在Java并发中，countdownlatch的概念是一个常见的面试题，所以一定要确保你很好的理解了它。
 * CountDownLatch 的三种典型用法:
 * ①某一线程在开始运行前等待n个线程执行完毕。将 CountDownLatch 的计数器初始化为n ：new CountDownLatch(n) ，
 * 每当一个任务线程执行完毕，就将计数器减1 countdownlatch.countDown()，当计数器的值变为0时，在CountDownLatch上 await() 的线程就会被唤醒。
 * 一个典型应用场景就是启动一个服务时，主线程需要等待多个组件加载完毕，之后再继续执行。
 *
 * ②实现多个线程开始执行任务的最大并行性。注意是并行性，不是并发，强调的是多个线程在某一时刻同时开始执行。类似于赛跑，将多个线程放到起点，
 * 等待发令枪响，然后同时开跑。做法是初始化一个共享的 CountDownLatch 对象，将其计数器初始化为 1 ：new CountDownLatch(1) ，
 * 多个线程在开始执行任务前首先 coundownlatch.await()，当主线程调用 countDown() 时，计数器变为0，多个线程同时被唤醒。
 *
 * ③死锁检测：一个非常方便的使用场景是，你可以使用n个线程访问共享资源，在每次测试阶段的线程数目是不同的，并尝试产生死锁。
 *
 * @date 2019/5/713:52
 */

public class CountDownLatchTestA {
    public static void main(String[] args) throws Exception{
        CountDownLatch countDownLatch = new CountDownLatch(6);
        for (int i = 0; i < 5; i++) {
            Thread thread = new Thread(new FirstThread(countDownLatch));
            thread.start();
        }
        for (int i = 0; i < 5; i++) {
            Thread thread = new Thread(new SecondThread(countDownLatch));
            thread.start();
        }
        while (countDownLatch.getCount()!=1){
            Thread.sleep(100L);
        }
        System.out.println("wait for first is finish!!");
        countDownLatch.countDown();
    }
}
class FirstThread implements Runnable{
    private CountDownLatch countDownLatch;
    public FirstThread(CountDownLatch countDownLatch){
        this.countDownLatch = countDownLatch;
    }
    @Override
    public void run() {
        System.out.println("First executed!!");
        countDownLatch.countDown();
    }
}
class SecondThread implements Runnable{
    private CountDownLatch countDownLatch;
    public SecondThread (CountDownLatch countDownLatch){
        this.countDownLatch = countDownLatch;
    }
    @Override
    public void run() {
        try {
            countDownLatch.await();
            System.out.println("second executed!!");
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
